//Winsed utility
using System;
using System.IO;

namespace WinSedApp   {

 
    //Class in charge of processing the command line arguments received during winsed invokation
    public class ArgProcessor
    {
        //Constants
        //Debug level: 0 is no debug. 1 verbose debug level
        private static int debugLevel = 0;
        private string programVersion = "Winsed 0.2.0, 2015";
        //Request to see the help file
        private string helpArgument = "--help";
        //Request to see the program version
        private string versionArgument = "--version";
        //Sed scripts
        private string scriptArgument = "-e";
        private string scriptArgumentLong = "--expression=";
        //Property holding the script to execute
        private string scriptToExeText;
        public string scriptToExe {
            get { return scriptToExeText; }
            set { scriptToExeText = value; }
        }
        //Property holding the file vs. standard input to treat
        private string stdInLiteral = "stdin";
        private string fileToProcText;
        public string fileToProc {
            get { return fileToProcText; }
            set { fileToProcText = value; }
        }
        //Property indicting if arguments were processed successfully
        private bool readyArgs = false;
        public bool readyArgsProp {
            get {return readyArgs; }
        }

        //Class constructor method
        public ArgProcessor (string[] argts) {
           
            // Test if input arguments were supplied:
            if (argts.Length == 0)
            {
                System.Console.WriteLine("No arguments were supplied."); 
                System.Console.WriteLine("To display online help: winsed --help");
            } else if (argts[0].Equals(helpArgument) ) {
                System.Console.WriteLine("");
                if (debugLevel > 0 ) { System.Console.WriteLine("Help text requested"); System.Console.WriteLine(""); }
                System.Console.WriteLine("Typical winsed command: winsed -e s/expression/replacement/g InputTextFile > OutputTextFile");
                System.Console.WriteLine("");
                System.Console.WriteLine("Or with spaces in the text to replace: winsed.exe -e s/\'tracert -d -h 16\'/\'tracert -d -h 8\'/g InputTextFile > OutputTextFile");
                System.Console.WriteLine("");
            } else if (argts[0].Equals(versionArgument) ) {
                if (debugLevel > 0 ) { System.Console.WriteLine("Program version requested"); }
                System.Console.WriteLine(programVersion);
            } else if (argts[0].Equals(scriptArgument)) {
                if (debugLevel > 0 ) {System.Console.WriteLine("Action script requested"); }
                if (argts.Length <= 1) {
                    System.Console.WriteLine("Second argument is missing");
                } else  {
                    scriptToExeText = argts[1];
                    scriptToExe = scriptToExeText;
                    if (debugLevel > 0) {System.Console.WriteLine("Script to execute:  " + scriptToExeText ); }
                    //Check what to process
                    if (argts.Length <= 2) {
                        System.Console.WriteLine("File input not specified, defaulting to standard input");
                        fileToProcText = stdInLiteral;
                        fileToProc = fileToProcText;
                    } else {
                        fileToProcText = argts[2];
                        fileToProc = fileToProcText;
                    }
                    readyArgs = true;
                }
            } else if (argts[0].StartsWith(scriptArgumentLong)) {
                if (debugLevel > 0) { System.Console.WriteLine("Action script requested"); }
                scriptToExeText = argts[0].Substring(scriptArgumentLong.Length);
                scriptToExe = scriptToExeText;
                if (debugLevel > 0) { System.Console.WriteLine("Script to execute:  " + scriptToExeText ); }
                //Check what to process
                    if (argts.Length <= 1) {
                        System.Console.WriteLine("File input not specified, defaulting to standard input");
                        fileToProcText = stdInLiteral;
                        fileToProc = fileToProcText;
                    } else {
                        fileToProcText = argts[1];
                        fileToProc = fileToProcText;
                    }
                    readyArgs = true;
            }
            else {
                System.Console.WriteLine("Arguments not recognized");
            }

        }

    }

    public class  FileInput  {

        //Property indicating the the file has been found
        private bool fileFound = false;
        public bool fileFoundProp {
            get {return fileFound; }
        }

        //Class constructor
        public FileInput (string myFileName) {
            string path = myFileName;
            if (File.Exists(path))  {
                fileFound = true;

            }
            else {
                
            }
        }
    }

    public class LineProcessor {

        //Debug level: 0 is no debug. 1 normal debug level
        private static int debugLevel = 0;

        //Property indicting if the script were processed successfully
        private bool readyScript = false;
        public bool readyScriptProp {
            get {return readyScript; }
        }

        //Strings with each of the string components
        private string commandFirst;
        private string regexpSecond;
        private string replacementThird;
        private string globalForth;

        //Method to process lines
        public string ProcessLine (string MyLine) {

            if (commandFirst.Equals("s")) {
                if (String.IsNullOrEmpty(regexpSecond)) {

                    }   else {
                        if (String.IsNullOrEmpty(replacementThird)) {

                            } else {
                                if (String.IsNullOrEmpty(globalForth)) {

                                    } else {
                                        MyLine = MyLine.Replace(regexpSecond,replacementThird);
                                    }
                            }

                    }                 
            }

            return MyLine;

        }
        
        //Constructor
        public LineProcessor (string MyScript) {

            //Split the script string
            string[] words = MyScript.Split('/');
            //Show the script components
            int i = 0;
            foreach (string word in words)
                {
                    //System.Console.WriteLine(word);
                    switch  (i) {
                            case 0:
                                commandFirst = word;
                                break;
                            case 1:
                                regexpSecond = word;
                                break;
                            case 2:
                                replacementThird = word;
                                break;
                            case 3:
                                globalForth = word;
                                break;
                            default:
                                System.Console.WriteLine ("Too many script arguments");
                                break;
                    }

                    i++;
                }
                //Debug data
                if (debugLevel > 0 ) {
                    System.Console.WriteLine("DEBUG");
                    System.Console.WriteLine (commandFirst);
                    System.Console.WriteLine (regexpSecond);
                    System.Console.WriteLine (replacementThird);
                    System.Console.WriteLine (globalForth);
                    }
        }

    }

    //Main class
    class MainClass
    {

        //public string stdInLiteral = "stdin";
        //Debug level: 0 is no debug. 1 normal debug level
        private static int debugLevel = 0;

        static int Main(string[] args)
        {
            //Instantiate the command line arguments object
            ArgProcessor MyArgs = new ArgProcessor (args); 

            if (debugLevel > 0 ) { System.Console.WriteLine("Resuming main class"); }

            //if arg processing completed successfully the proceed with text stream/file processing
            if (MyArgs.readyArgsProp) {
                    if (debugLevel >0 ) { System.Console.WriteLine("  Script that will be passed to script parser: " + MyArgs.scriptToExe ); }                    //Parse action script
                    LineProcessor MyProcessor = new LineProcessor (MyArgs.scriptToExe);

                    if (MyArgs.fileToProc.Equals("stdin") )
                        {
                                if (debugLevel >0 ) { System.Console.WriteLine(" Processing stdin"); }
                        } else {
                                if (debugLevel >0 ) { System.Console.WriteLine(" Processing text file: " + MyArgs.fileToProc); }
                                
                                FileInput MyFile = new FileInput (MyArgs.fileToProc);

                                if (MyFile.fileFoundProp) {
                                        if (debugLevel >0 ) { System.Console.WriteLine(" Input file found"); }

                                        //Load Text file
                                        string line;
                                        // Read the file and display it line by line.
                                        System.IO.StreamReader file = new System.IO.StreamReader(@MyArgs.fileToProc);
                                        while((line = file.ReadLine()) != null)
                                            {
                                                //System.Console.WriteLine (line);
                                                //Do the processing
                                                if (debugLevel >0 ) { System.Console.WriteLine ("Processing line: " + line); }
                                                System.Console.WriteLine (MyProcessor.ProcessLine(line));

                                            }
                                        //Close the text file
                                        file.Close();

                                    } else {
                                        System.Console.WriteLine(" Input file NOT found");
                                    }
                        }

            } else 
            //Args not recognized
            {
                    System.Console.WriteLine("  Arguments not recognized");
            }
            

            return 0;

        }
    }

}

